﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GDIScreenCapture
{
    public partial class frmCapture : Form
    {

        // GDI绘图类
        Graphics _graphics;
        //标识鼠标是否是按下拖动的状态，用来标识截图是否开始
        bool _isPressed = false;
        //鼠标按下的点，鼠标的开始点
        Point _beginPoint;
        //自定义绘图类
        Drawing _drawing;
        //屏幕图片
        Bitmap screenImage;
        //截取的区域
        Rectangle _captureRect;

        public frmCapture()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 截图的初始方法
        /// </summary>
        void InitScreenCapture()
        {
            //初始化截图资源
            ComputerScreen cs = new ComputerScreen();
            this.screenImage = cs.PrintScreen();
            this.pbScreen.Image = (Image)screenImage.Clone();
            this._drawing = new Drawing();

            this.Show();
            //将窗体设置为无边框窗体
            this.FormBorderStyle = FormBorderStyle.None;
            //最大化窗体
            this.WindowState = FormWindowState.Maximized;
        }

        /// <summary>
        /// 鼠标按下时候触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pbScreen_MouseDown(object sender, MouseEventArgs e)
        {
            this._isPressed = true;
            this._beginPoint = new Point(e.X, e.Y);
        }

        /// <summary>
        /// 鼠标弹起时触发的事件,表示绘图结束，可以在这里进行释放资源的操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pbScreen_MouseUp(object sender, MouseEventArgs e) 
        {
            if (e.Button == MouseButtons.Left)
            {
                this._isPressed = false;
                //释放绘图过程中占用的资源
                GC.Collect();

                //截屏操作
                Bitmap btmCapture = new Bitmap(_captureRect.Width, _captureRect.Height);
                using (Graphics g = Graphics.FromImage(btmCapture))
                {
                    //在真个屏幕的图片的基础上绘制出选中的区域，实现截图功能
                    g.DrawImage(this.screenImage, new Rectangle(0, 0, this._captureRect.Width, this._captureRect.Height), this._captureRect, GraphicsUnit.Pixel);
                    //将图片放置到剪切板
                    Clipboard.SetImage(btmCapture);

                    //释放占用的资源
                    this.screenImage.Dispose();
                    btmCapture.Dispose();

                    //隐藏窗体等待下次调用
                    this.Hide();

                    //GC回收资源
                    GC.Collect();
                }

            }
        }

        /// <summary>
        ///鼠标移动时候触发的事件 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pbScreen_MouseMove(object sender, MouseEventArgs e)
        {
            if (!this._isPressed)
            {
                return;
            }

            //获取到当前的picturebox上加载的图片，方便待会释放资源
            Image lastCloneImg = this.pbScreen.Image;

            /*
             * 创建新屏幕图片的对象, 这一步操作会花费大量的资源，所以要在使用以后立即处理掉
             * 这是一个新的图像，我们将在此图像上继续绘制截图范围的边框，每一次移动鼠标都吃在新的图片上重新绘制
             * 以达到动态的绘制矩形的效果
             */
            Image cloneImg = (Image)this.screenImage.Clone();

            //释放上一个的绘图资源
            if (_graphics != null)
            {
                this._graphics.Dispose();
            }

            //重新建立绘图工具类
            using (this._graphics = Graphics.FromImage(cloneImg))
            {
                //在新的图片上绘制矩形
                _captureRect = this._drawing.DrawRect(this._beginPoint, new Point(e.X, e.Y), _graphics);
                //将新图片重新赋值到PictureBox
                this.pbScreen.Image = cloneImg;

                //释放旧的图片所占用的资源
                lastCloneImg.Dispose();
            }
        }

        /// <summary>
        /// 右键菜单的点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmCaputre_Click(object sender, EventArgs e)
        {
            this.InitScreenCapture();
        }

        /// <summary>
        /// 窗体显示后触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmCapture_Shown(object sender, EventArgs e)
        {
            //将窗体隐藏，并将截图的触发方式缩小的最小托盘
            this.Hide();
            this.notifyScreenCapture.Visible = true;
        }
    }
}
